﻿using IM.Easy.AuthorizationServices.Dtos;
using IM.Easy.AuthorizationServices.IServices;
using IM.Easy.Core.AppContext;
using IM.Easy.Core.Constants;
using IM.Easy.Core.Enums;
using IM.Easy.Core.Extensions;
using IM.Easy.Core.Options;
using IM.Easy.Core.Result;
using IM.Easy.Core.Security;
using IM.Easy.Core.Services;
using IM.Easy.Core.Utils;
using IM.Easy.CoreServices.IServices;
using IM.Easy.Entity.System;
using IM.Easy.Infrastructure.Constants;
using Mapster;
using Microsoft.AspNetCore.Authentication.BearerToken;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;


namespace IM.Easy.AuthorizationServices.Services
{

    public class IdentityService : AppServices, IIdentityService
    {
        private readonly IParamsService _paramsService;
        public IdentityService(ISqlSugarClient db, IParamsService paramsService) : base(db)
        {
            _paramsService = paramsService;
        }

        /// <summary>
        /// 获取登录用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public ApiResult<LoginUser> GetLoginUser(LoginInput input)
        {
            var maxAttempts = _paramsService.GetValue<int>(ParamsConstant.AccountLocked);
            var result = new ApiResult<LoginUser>();

            var user = Db.Queryable<SysUser>()
                        .Includes(s => s.Security)
                        .First(s => s.UserName == input.UserName);
            // 用户不存在
            if (user == null)
            {
                return ApiResult<LoginUser>.Failure("账户不存在", ResultCode.BusinessLogicError);
            }
            user.Security ??= new SysAccountSecurity() { Id = SnowFlakeSingle.Instance.NextId(), UserId = user.Id };

            // 账户状态检查
            if (!ValidateAccountStatus(user, out var errorMessage))
            {
                return ApiResult<LoginUser>.Failure(errorMessage, ResultCode.BusinessLogicError);
            }

            // 密码验证失败
            if (!Sha256Hash.ValidateHash(input.Password, user.Password))
            {
                HandleFailedLogin(user, maxAttempts);
                return ApiResult<LoginUser>.Failure("密码错误", ResultCode.BusinessLogicError);
            }
            // 登录成功处理
            var loginUser = HandleSuccessfulLogin(user);
            return ApiResult<LoginUser>.Success(loginUser);
        }

        /// <summary>
        /// 账户状态校验（解耦核心逻辑）
        /// </summary>
        /// <param name="user"></param>
        /// <param name="errorMessage"></param>
        /// <returns></returns>
        private bool ValidateAccountStatus(SysUser user, out string errorMessage)
        {
            errorMessage = string.Empty;

            if (!user.IsActive)
            {
                errorMessage = "账户未启用";
                return false;
            }

            if (user.Security?.IsLocked == true)
            {
                errorMessage = "账户已被锁定";
                return false;
            }

            return true;
        }

        /// <summary>
        /// 登录成功处理
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        private LoginUser HandleSuccessfulLogin(SysUser user)
        {
            user.Security ??= new SysAccountSecurity() { Id = SnowFlakeSingle.Instance.NextId(), UserId = user.Id };
            user.Security.FailedAttempts = 0;
            user.Security.LockedAt = null;
            user.Security.LastFailedAt = null;
            user.Security.LastLoginAt = DateTime.Now;

            Db.GetSimpleClient<SysAccountSecurity>().InsertOrUpdate(user.Security);

            var loginUser = user.Adapt<LoginUser>();
            loginUser.ClientId = ImApp.Current.GetClientId();
            return loginUser;
        }

        /// <summary>
        /// 登录失败处理 
        /// </summary>
        /// <param name="user"></param>
        /// <param name="maxAttempts"></param>
        private void HandleFailedLogin(SysUser user, int maxAttempts)
        {
            user.Security ??= new SysAccountSecurity() { Id = SnowFlakeSingle.Instance.NextId(), UserId = user.Id };
            user.Security.FailedAttempts++;

            if (user.Security.FailedAttempts >= maxAttempts)
            {
                user.Security.IsLocked = true;
                user.Security.LockedAt = DateTime.Now;
            }

            user.Security.LastFailedAt = DateTime.Now;

            Db.GetSimpleClient<SysAccountSecurity>().InsertOrUpdate(user.Security);
        }

        /// <summary>
        /// 绑定登录用户的角色
        /// </summary>
        /// <returns></returns>
        public void BindRoles(LoginUser user)
        {
            var roles = new List<LoginUserRole>();

            if (user.IsSuperAdmin)
            {
                roles.Add(new LoginUserRole()
                {
                    Code = "superAdmin",
                    Name = "超级管理员",
                    Perms = "*:*:*",
                });
            }
            else
            {
                //roles = Db.Queryable<SysRole>()
                // .InnerJoin<SysUserRole>((r, ur) => r.Id == ur.RoleId)
                // .Where((r, ur) => ur.UserId == user.Id)
                // .Select((r, ur) => r)
                // .ToList()
                // .Adapt<List<LoginUserRole>>();
            }
            user.Roles = roles;
        }

        /// <summary>
        /// 绑定登录用户的权限
        /// </summary>
        /// <returns></returns>
        public void BindPermission(LoginUser user)
        {
            //var perms = new List<string>();
            //if (user.IsSuperAdmin)
            //    perms.Add("*:*:*");
            //else
            //{
            //    var menus = Db.Queryable<SysMenu, SysRoleMenu, SysUserRole, SysRole>((m, rm, ur, r) => new JoinQueryInfos(
            //           JoinType.Left, m.Id == rm.MenuId,
            //           JoinType.Left, rm.RoleId == ur.RoleId,
            //           JoinType.Left, ur.RoleId == r.Id
            //   ))
            //   .Where((m, rm, ur, r) => ur.UserId == user.Id)
            //   .Select((m, rm, ur, r) => m).ToList();
            //    var menuList = menus.Where(f => !string.IsNullOrEmpty(f.Perms));

            //    perms = menuList.Select(x => x.Perms).Distinct().ToList();
            //}
            //user.Perms = perms;
        }

        /// <summary>
        /// 颁发token
        /// </summary>
        /// <returns></returns>
        public string IssureAccessToken(LoginUser user)
        {
            var payload = new Dictionary<string, object>
            {
                { ClaimTypes.PrimarySid,user.Id },
                { ClaimTypes.NameIdentifier, user.UserName },
                { ClaimTypes.Name, user.NickName },
                { ClaimConstTypes.ClientId, user.ClientId },
                { ClaimConstTypes.Provider,user.Provider }
            };

            // 生成 token
            var accessToken = JwtEncryption.EncryptToken(payload);

            //写入缓存
            return accessToken;
        }

        /// <summary>
        /// 颁发token
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public string IssureAccessToken(long userId)
        {
            var user = Db.Queryable<SysUser>().InSingle(userId);
            var loginUser = user.Adapt<LoginUser>();
            var accessToken = IssureAccessToken(loginUser);
            return accessToken;
        }
    }
}
